function RefreshPowerPlantTextTag takes unit powerPlant returns nothing
	local integer powerPlantId = GetHandleId(powerPlant)
	local integer powerPlantTypeId = GetUnitTypeId(powerPlant)
	local texttag tag = LoadTextTagHandle(udg_UnitDataHashTable , powerPlantId , StringHash("POWER_PLANT_TEXT_TAG"))
	local integer supplyRemain = LoadInteger(udg_UnitTypeDataHashTable , powerPlantTypeId , StringHash("POWER_SUPPLY_MAX")) - LoadInteger(udg_UnitDataHashTable , powerPlantId , StringHash("POWER_PLANT_SUPPLY_USED"))
	local string text = "剩餘電力：" + I2S(supplyRemain)
	local real xOffsset = 67.0
	//--
	if tag == null then
		set tag = CreateTextTag()
		call SaveTextTagHandle(udg_UnitDataHashTable , powerPlantId , StringHash("POWER_PLANT_TEXT_TAG") , tag)
	endif
	call SetTextTagText(tag , text , 0.0276)
	call SetTextTagPos(tag , GetUnitX(powerPlant) - xOffsset , GetUnitY(powerPlant) , 200.0)
	call SetTextTagColor(tag , 255 , 255 , 255 , 0)
	//--
	set tag = null
	set text = null
endfunction

function RefreshNeedSupplyBuildingTextTag takes unit building returns nothing
	local integer buildingId = GetHandleId(building)
	local integer buildingTypeId = GetUnitTypeId(building)
	local texttag tag = LoadTextTagHandle(udg_UnitDataHashTable , buildingId , StringHash("NEED_POWER_SUPPLY_BUILDING_TEXT_TAG"))
	local integer supplyNeededRemain = LoadInteger(udg_UnitTypeDataHashTable , buildingTypeId , StringHash("SUPPLY_NEEDED")) - LoadInteger(udg_UnitDataHashTable , buildingId , StringHash("SUPPLY_NOW"))
	local string text = null
	local real xOffsset = 60.0
	//--
	if tag == null then
		set tag = CreateTextTag()
		call SaveTextTagHandle(udg_UnitDataHashTable , buildingId , StringHash("NEED_POWER_SUPPLY_BUILDING_TEXT_TAG") , tag)
	endif
	if supplyNeededRemain > 0 then
		set text = "電力需求：" + I2S(supplyNeededRemain)
		call SetTextTagColor(tag , 255 , 0 , 0 , 0)
	else
		set text = "供電正常"
		call SetTextTagColor(tag , 0 , 255 , 0 , 0)
	endif
	call SetTextTagText(tag , text , 0.02)	
	call SetTextTagPos(tag , GetUnitX(building) - xOffsset , GetUnitY(building) , 50.0)
	
	//--
	set tag = null
	set text = null
endfunction

function DestroyPowerSupplyConnection takes unit powerPlant , unit building returns nothing
	local integer powerPlantTypeId = GetUnitTypeId(powerPlant)
	local integer powerPlantId = GetHandleId(powerPlant)
	local integer supplyMax = LoadInteger(udg_UnitTypeDataHashTable , powerPlantTypeId , StringHash("POWER_SUPPLY_MAX"))
	local integer supplyUsed = LoadInteger(udg_UnitDataHashTable , powerPlantId , StringHash("POWER_PLANT_SUPPLY_USED"))
	local integer powerPlantSupplyRemain = supplyMax - supplyUsed
	local group suppliedBuildings = LoadGroupHandle(udg_UnitDataHashTable , powerPlantId , StringHash("SUPPLIED_BUILDINGS"))
	local hashtable supplyTable = LoadHashtableHandle(udg_UnitDataHashTable , powerPlantId , StringHash("SUPPLY_TABLE"))
	local integer buildingId = GetHandleId(building)
	local integer buildingTypeId = GetUnitTypeId(building)
	local group usingPowerPlants = LoadGroupHandle(udg_UnitDataHashTable , buildingId , StringHash("USING_POWER_PLANTS"))
	local integer supplyNeededByThisBuilding = LoadInteger(udg_UnitTypeDataHashTable , buildingTypeId , StringHash("SUPPLY_NEEDED"))
	local integer supplyOwnedByThisBuildingNow = LoadInteger(udg_UnitDataHashTable , buildingId , StringHash("SUPPLY_NOW"))
	local integer supplyProvidedByThisPowerPlant = LoadInteger(supplyTable , buildingId , StringHash("SUPPLY_USED"))
	local lightning connectionLightning = LoadLightningHandle(supplyTable , buildingId , StringHash("POWER_SUPPLY_LIGHTNING"))
	//--
	call SaveInteger(udg_UnitDataHashTable , powerPlantId , StringHash("POWER_PLANT_SUPPLY_USED") , supplyUsed - supplyProvidedByThisPowerPlant)
	call GroupRemoveUnit(suppliedBuildings , building)
	call GroupRemoveUnit(usingPowerPlants , powerPlant)
	call DestroyLightning(connectionLightning)
	set supplyOwnedByThisBuildingNow = supplyOwnedByThisBuildingNow - supplyProvidedByThisPowerPlant
	call SaveInteger(udg_UnitDataHashTable , buildingId , StringHash("SUPPLY_NOW") , supplyOwnedByThisBuildingNow)
	if supplyNeededByThisBuilding > supplyOwnedByThisBuildingNow and LoadBoolean(udg_UnitDataHashTable , GetHandleId(building) , StringHash("CONSTRUCTION_FINISHED")) then
		call PauseUnit(building , true)
	endif
	call RefreshPowerPlantTextTag(powerPlant)
	call RefreshNeedSupplyBuildingTextTag(building)
	call FlushChildHashtable(supplyTable , buildingId)
	//--
	set suppliedBuildings = null
	set supplyTable = null
	set usingPowerPlants = null
	set connectionLightning = null
endfunction

function CreatePowerSupplyConnection takes unit powerPlant , unit building returns nothing
	local integer powerPlantTypeId = GetUnitTypeId(powerPlant)
	local integer powerPlantId = GetHandleId(powerPlant)
	local integer supplyMax = LoadInteger(udg_UnitTypeDataHashTable , powerPlantTypeId , StringHash("POWER_SUPPLY_MAX"))
	local integer supplyUsed = LoadInteger(udg_UnitDataHashTable , powerPlantId , StringHash("POWER_PLANT_SUPPLY_USED"))
	local integer powerPlantSupplyRemain = supplyMax - supplyUsed
	local group suppliedBuildings = LoadGroupHandle(udg_UnitDataHashTable , powerPlantId , StringHash("SUPPLIED_BUILDINGS"))
	local hashtable supplyTable = LoadHashtableHandle(udg_UnitDataHashTable , powerPlantId , StringHash("SUPPLY_TABLE"))
	local integer buildingId = GetHandleId(building)
	local integer buildingTypeId = GetUnitTypeId(building)
	local group usingPowerPlants = LoadGroupHandle(udg_UnitDataHashTable , buildingId , StringHash("USING_POWER_PLANTS"))
	local integer supplyNeededByThisBuilding = LoadInteger(udg_UnitTypeDataHashTable , buildingTypeId , StringHash("SUPPLY_NEEDED"))
	local integer supplyOwnedByThisBuildingNow = LoadInteger(udg_UnitDataHashTable , buildingId , StringHash("SUPPLY_NOW"))
	local integer realSupplyUsedByThisBuilding = 0
	local integer supplyNeededRemain = supplyNeededByThisBuilding - supplyOwnedByThisBuildingNow
	local lightning connectionLightning = AddLightning("CLSB" , true , GetUnitX(powerPlant) , GetUnitY(powerPlant) , GetUnitX(building) , GetUnitY(building))
	//--
	if powerPlantSupplyRemain < supplyNeededRemain then
		set realSupplyUsedByThisBuilding = powerPlantSupplyRemain
	else
		set realSupplyUsedByThisBuilding = supplyNeededRemain
	endif

	call SaveInteger(udg_UnitDataHashTable , powerPlantId , StringHash("POWER_PLANT_SUPPLY_USED") , supplyUsed + realSupplyUsedByThisBuilding)
	call GroupAddUnit(suppliedBuildings , building)
	call SaveInteger(supplyTable , buildingId , StringHash("SUPPLY_USED") , realSupplyUsedByThisBuilding)
	call SetLightningColor(connectionLightning , 1.0 , 1.0 , 1.0 , 0.2)
	call SaveLightningHandle(supplyTable , buildingId , StringHash("POWER_SUPPLY_LIGHTNING") , connectionLightning)
	call GroupAddUnit(usingPowerPlants , powerPlant)
	set supplyOwnedByThisBuildingNow = supplyOwnedByThisBuildingNow + realSupplyUsedByThisBuilding
	call SaveInteger(udg_UnitDataHashTable , buildingId , StringHash("SUPPLY_NOW") , supplyOwnedByThisBuildingNow)
	if supplyNeededByThisBuilding <= supplyOwnedByThisBuildingNow then
		call PauseUnit(building , false)
	endif
	call RefreshPowerPlantTextTag(powerPlant)
	call RefreshNeedSupplyBuildingTextTag(building)
	//--
	set suppliedBuildings = null
	set supplyTable = null
	set usingPowerPlants = null
	set connectionLightning = null
endfunction

function DestroyThisConnection takes nothing returns nothing
	call DestroyPowerSupplyConnection(udg_TempUnit , GetEnumUnit())
endfunction

function DestroyThisConnectionSwaped takes nothing returns nothing
	call DestroyPowerSupplyConnection(GetEnumUnit() , udg_TempUnit)
endfunction

function DestroyPowerplantAllConnections takes unit powerPlant returns nothing
	set udg_TempUnit = powerPlant
	call ForGroup(LoadGroupHandle(udg_UnitDataHashTable , GetHandleId(powerPlant) , StringHash("SUPPLIED_BUILDINGS")) , function DestroyThisConnection)
endfunction

function PowerPlantDeadAction takes nothing returns nothing
	local unit powerPlant = GetTriggerUnit()
	local integer powerPlantId = GetHandleId(powerPlant)
	local group supplyBuildings = LoadGroupHandle(udg_UnitDataHashTable , powerPlantId , StringHash("SUPPLIED_BUILDINGS"))
	local hashtable supplyTable = LoadHashtableHandle(udg_UnitDataHashTable , powerPlantId , StringHash("SUPPLY_TABLE"))
	local trigger deadTrigger = GetTriggeringTrigger()
	local timer chargeTimer = LoadTimerHandle(udg_UnitDataHashTable , powerPlantId , StringHash("POWER_PLANT_CHARGE_TIMER"))
	//--
	call DestroyPowerplantAllConnections(powerPlant)
	call DestroyTextTag(LoadTextTagHandle(udg_UnitDataHashTable , powerPlantId , StringHash("POWER_PLANT_TEXT_TAG")))
	call DestroyGroup(supplyBuildings)
	call FlushParentHashtable(supplyTable)
	call TriggerRemoveAction(deadTrigger , LoadTriggerActionHandle(udg_TriggerDataHashTable , GetHandleId(deadTrigger) , StringHash("TRIGGER_ACTION")))
	call FlushChildHashtable(udg_TriggerDataHashTable , GetHandleId(deadTrigger))
	call DestroyTrigger(deadTrigger)
	call FlushChildHashtable(udg_UnitDataHashTable , powerPlantId)
	call PauseTimer(chargeTimer)
	call FlushChildHashtable(udg_HT , GetHandleId(chargeTimer))
	call DestroyTimer(chargeTimer)
	//--
	set powerPlant = null
	set supplyBuildings = null
	set supplyTable = null
	set deadTrigger = null
	set chargeTimer = null
endfunction

function CreatePowerPlantDeadTrigger takes unit powerPlant returns nothing
	local trigger deadTrigger = CreateTrigger()
	//--
	call TriggerRegisterUnitEvent(deadTrigger , powerPlant , EVENT_UNIT_DEATH)
	call SaveTriggerActionHandle(udg_TriggerDataHashTable , GetHandleId(deadTrigger) , StringHash("TRIGGER_ACTION") , TriggerAddAction(deadTrigger , function PowerPlantDeadAction))
	//--
	set deadTrigger = null
endfunction

function DestroyBuildingAllConnections takes unit building returns nothing
	set udg_TempUnit = building
	call ForGroup(LoadGroupHandle(udg_UnitDataHashTable , GetHandleId(building) , StringHash("USING_POWER_PLANTS")) , function DestroyThisConnectionSwaped)
endfunction

function NeedSupplyBuildingDeadAction takes nothing returns nothing
	local unit building = GetTriggerUnit()
	local integer buildingId = GetHandleId(building)
	local group usingPowerPlants = LoadGroupHandle(udg_UnitDataHashTable , buildingId , StringHash("USING_POWER_PLANTS"))
	local trigger deadTrigger = GetTriggeringTrigger()
	local boolean isReplaced = LoadBoolean(udg_UnitDataHashTable , buildingId , StringHash("IS_REPLACED"))
	//--
	if not isReplaced then
		call DestroyBuildingAllConnections(building)
		call DestroyTextTag(LoadTextTagHandle(udg_UnitDataHashTable , buildingId , StringHash("NEED_POWER_SUPPLY_BUILDING_TEXT_TAG")))
		call DestroyGroup(usingPowerPlants)		
		call FlushChildHashtable(udg_UnitDataHashTable , buildingId)
	endif
	call TriggerRemoveAction(deadTrigger , LoadTriggerActionHandle(udg_TriggerDataHashTable , GetHandleId(deadTrigger) , StringHash("TRIGGER_ACTION")))
	call FlushChildHashtable(udg_TriggerDataHashTable , GetHandleId(deadTrigger))
	call DestroyTrigger(deadTrigger)
	//--
	set building = null
	set usingPowerPlants = null
	set deadTrigger = null
endfunction

function CreateNeedSupplyBuildingDeadTrigger takes unit building returns nothing
	local trigger deadTrigger = CreateTrigger()
	//--
	call TriggerRegisterUnitEvent(deadTrigger , building , EVENT_UNIT_DEATH)
	call SaveTriggerActionHandle(udg_TriggerDataHashTable , GetHandleId(deadTrigger) , StringHash("TRIGGER_ACTION") , TriggerAddAction(deadTrigger , function NeedSupplyBuildingDeadAction))
	//--
	set deadTrigger = null
endfunction

function ChargeAction takes nothing returns nothing
	local timer chargeTimer = GetExpiredTimer()
	local unit powerPlant = LoadUnitHandle(udg_HT , GetHandleId(chargeTimer) , 0)
	local integer slotIndex = 0
	local item whichItem = null
	//--
	loop
		exitwhen slotIndex >= 6
		set whichItem = UnitItemInSlot(powerPlant , slotIndex)	
		if LoadBoolean(udg_ItemTypeDataHashTable , GetItemTypeId(whichItem) , StringHash("IS_CHARGEABLE")) then
			if GetItemCharges(whichItem) < LoadInteger(udg_ItemTypeDataHashTable , GetItemTypeId(whichItem) , StringHash("CAPACITY")) then
				call SetItemCharges(whichItem , GetItemCharges(whichItem) + 1)
			endif
		endif
		set slotIndex = slotIndex + 1
	endloop
	//--
	set chargeTimer = null
	set powerPlant = null
endfunction

function CreateChargeTimer takes unit powerPlant returns nothing
	local timer chargeTimer = CreateTimer()
	//--
	call SaveUnitHandle(udg_HT , GetHandleId(chargeTimer) , 0 , powerPlant)
	call TimerStart(chargeTimer , 1.0 , true , function ChargeAction)
	call SaveTimerHandle(udg_UnitDataHashTable , GetHandleId(powerPlant) , StringHash("POWER_PLANT_CHARGE_TIMER") , chargeTimer)
	//--
	set chargeTimer = null
endfunction

function InitializePowerPlant takes unit powerPlant returns nothing
	local integer powerPlantId = GetHandleId(powerPlant)
	local integer powerPlantTypeId = GetUnitTypeId(powerPlant)
	//--
	call SaveGroupHandle(udg_UnitDataHashTable , powerPlantId , StringHash("SUPPLIED_BUILDINGS") , CreateGroup())
	call SaveHashtableHandle(udg_UnitDataHashTable , powerPlantId , StringHash("SUPPLY_TABLE") , InitHashtable())
	call SaveInteger(udg_UnitDataHashTable , powerPlantId , StringHash("POWER_PLANT_SUPPLY_USED") , 0)
	call RefreshPowerPlantTextTag(powerPlant)
	call CreateChargeTimer(powerPlant)
	call CreatePowerPlantDeadTrigger(powerPlant)
endfunction

function SupplyBuildingEnterMap takes nothing returns nothing
	local unit newUnit = GetTriggerUnit()
	local integer newUnitId = GetHandleId(newUnit)
	local integer newUnitTypeId = GetUnitTypeId(newUnit)
	//--
	if LoadBoolean(udg_UnitTypeDataHashTable , newUnitTypeId , StringHash("IS_POWER_PLANT")) then	//是發電廠
		call InitializePowerPlant(newUnit)
	elseif LoadBoolean(udg_UnitTypeDataHashTable , newUnitTypeId , StringHash("NEED_POWER_SUPPLY")) then //需要供電
		if not HaveSavedHandle(udg_UnitDataHashTable , newUnitId , StringHash("USING_POWER_PLANTS")) then //不是取代的新部隊
			call SaveGroupHandle(udg_UnitDataHashTable , newUnitId , StringHash("USING_POWER_PLANTS") , CreateGroup())
			call SaveInteger(udg_UnitDataHashTable , newUnitId , StringHash("SUPPLY_NOW") , 0)
			call RefreshNeedSupplyBuildingTextTag(newUnit)
		endif
		call CreateNeedSupplyBuildingDeadTrigger(newUnit)
	endif
	//--
	set newUnit = null
endfunction

function PowerSupplyAction takes nothing returns nothing
	local unit powerPlant = GetTriggerUnit()
	local integer powerPlantId = GetHandleId(powerPlant)
	local group suppliedBuildings = LoadGroupHandle(udg_UnitDataHashTable , powerPlantId , StringHash("SUPPLIED_BUILDINGS"))
	local integer powerPlantSupplyRemain = LoadInteger(udg_UnitTypeDataHashTable , GetUnitTypeId(powerPlant) , StringHash("POWER_SUPPLY_MAX")) - LoadInteger(udg_UnitDataHashTable , powerPlantId , StringHash("POWER_PLANT_SUPPLY_USED"))
	local unit building = GetSpellTargetUnit()
	local integer buildingId = GetHandleId(building)
	local integer supplyNeededByThisBuilding = LoadInteger(udg_UnitTypeDataHashTable , GetUnitTypeId(building) , StringHash("SUPPLY_NEEDED"))
	local integer supplyOwnedByThisBuildingNow = LoadInteger(udg_UnitDataHashTable , buildingId , StringHash("SUPPLY_NOW"))
	//--
	if not LoadBoolean(udg_UnitTypeDataHashTable , GetUnitTypeId(building) , StringHash("NEED_POWER_SUPPLY")) then
		call PrintP(GetTriggerPlayer() , "這個單位不須供電")
	elseif IsUnitInGroup(building , suppliedBuildings) then //取消連線
		call DestroyPowerSupplyConnection(powerPlant , building)
	elseif supplyOwnedByThisBuildingNow >= supplyNeededByThisBuilding then
		call PrintP(GetTriggerPlayer() , "這個單位已經擁有足夠的電力")
	elseif powerPlantSupplyRemain <= 0 then
		call PrintP(GetTriggerPlayer() , "沒有多餘的電力")
	else
		call CreatePowerSupplyConnection(powerPlant , building)
	endif
	//--
	set suppliedBuildings = null
	set building = null
endfunction

function NeedSupplyBuildingConstructionStart takes nothing returns nothing
	local unit building = GetTriggerUnit()
	local integer typeId = GetUnitTypeId(building)
	if LoadBoolean(udg_UnitTypeDataHashTable , typeId , StringHash("NEED_POWER_SUPPLY")) then
		call SaveBoolean(udg_UnitDataHashTable , GetHandleId(building) , StringHash("CONSTRUCTION_FINISHED") , false)
	endif 
	set building = null
endfunction

function NeedSupplyBuildingConstructionFinish takes nothing returns nothing
	local unit building = GetTriggerUnit()
	local integer typeId = GetUnitTypeId(building)
	if LoadBoolean(udg_UnitTypeDataHashTable , typeId , StringHash("NEED_POWER_SUPPLY")) then
		call SaveBoolean(udg_UnitDataHashTable , GetHandleId(building) , StringHash("CONSTRUCTION_FINISHED") , true)
	endif 
	set building = null
endfunction

function PowerSupplyAbilityTestAction takes nothing returns nothing
	if GetSpellAbilityId() == 'A01B' then
		call PowerSupplyAction()
	endif
endfunction

function InitTrig_PowerSupplySystem takes nothing returns nothing
	local trigger powerSupplyAbilityTrigger = CreateTrigger()
	local trigger supplyTextTagTrigger = CreateTrigger()
	local trigger constructionStartTrigger = CreateTrigger()
	local trigger constructionFinishTrigger = CreateTrigger()
	//--
	call TriggerRegisterPlayerForceUnitEvent(powerSupplyAbilityTrigger , EVENT_PLAYER_UNIT_SPELL_EFFECT)
	call TriggerAddAction(powerSupplyAbilityTrigger , function PowerSupplyAbilityTestAction)
	
	call TriggerRegisterEnterRectSimple(supplyTextTagTrigger , GetPlayableMapRect())
	call TriggerAddAction(supplyTextTagTrigger , function SupplyBuildingEnterMap)
	
	//開始建造
	call TriggerRegisterPlayerForceUnitEvent(constructionStartTrigger , EVENT_PLAYER_UNIT_CONSTRUCT_START)
	call TriggerAddAction(constructionStartTrigger , function NeedSupplyBuildingConstructionStart)
	
	//結束建造
	call TriggerRegisterPlayerForceUnitEvent(constructionFinishTrigger , EVENT_PLAYER_UNIT_CONSTRUCT_FINISH)
	call TriggerAddAction(constructionFinishTrigger , function NeedSupplyBuildingConstructionFinish)
	//--
	set powerSupplyAbilityTrigger = null
	set supplyTextTagTrigger = null
endfunction